﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media;
using System.Windows;
using System.Windows.Shapes;
using WickedFlame.Core.State;
using System.Windows.Media.Imaging;

namespace WickedFlame.Core.Shapes
{
	public class RectangleShape : RectangleBase, IStateCapturable, IPolygonShape, ICopyable
	{
        public RectangleShape()
            : base(0, 0, 1, 1)
        {
        }

        public RectangleShape(Point point, Size size)
            : base(point.X, point.Y, size.Width, size.Height)
        {
        }


        public RectangleShape(double x, double y, double width, double height)
            : base(x, y, width, height)
        {
        }

        #region Properties

        public override Rect Rectangle
        {
            get
            {
                return base.Rectangle;
            }
            set
            {
                base.Rectangle = value;
            }
        }

		public double Width
		{
			get
			{
				return Rectangle.Width;
			}
			set
			{
                Rectangle = new Rect(Rectangle.X, Rectangle.Y, value, Rectangle.Height);
                this.Invalidate();
			}
		}

		public double Height
		{
			get
			{
                return Rectangle.Height;
			}
			set
			{
                Rectangle = new Rect(Rectangle.X, Rectangle.Y, Rectangle.Width, value);
                this.Invalidate();
			}
		}

		public double X
		{
			get
			{
                return Rectangle.X;
			}
			set
			{
                Rectangle = new Rect(value, Rectangle.Y, Rectangle.Width, Rectangle.Height);
                this.Invalidate();
			}
		}

		public double Y
		{
			get
			{
                return Rectangle.Y;
			}
			set
			{
                Rectangle = new Rect(Rectangle.X, value, Rectangle.Width, Rectangle.Height);
                this.Invalidate();
			}
		}

		public double Right
		{
			get
			{
                return Rectangle.Right;
			}
		}

		public double Left
		{
			get
			{
                return Rectangle.Left;
			}
		}

        double _cornerRadius = 0.0;
        public double CornerRadius
        {
            get
            {
                return _cornerRadius;
            }
            set
            {
                _cornerRadius = value;
                this.Invalidate();
            }
        }

        #endregion

        public override void Draw(DrawingContext drawingContext)
        {
            //var pen = new Pen(Stroke, StrokeThickness);
            double halfPenWidth = Pen.Thickness / 2;

            // Create a guidelines set
            var guidelines = new GuidelineSet();
            guidelines.GuidelinesX.Add(Rectangle.Left + halfPenWidth);
            guidelines.GuidelinesX.Add(Rectangle.Right + halfPenWidth);
            guidelines.GuidelinesY.Add(Rectangle.Top + halfPenWidth);
            guidelines.GuidelinesY.Add(Rectangle.Bottom + halfPenWidth);

            drawingContext.PushGuidelineSet(guidelines);

            // rotate the shape
            if (Rotation > 0)
            {
                double centerX = Rectangle.X + (Rectangle.Width / 2);
                double centerY = Rectangle.Y + (Rectangle.Height / 2);
                drawingContext.PushTransform(new RotateTransform(Rotation, centerX, centerY));
            }

            if (CornerRadius > 0)
            {
                drawingContext.DrawRoundedRectangle(
                Fill,
                Pen,
                Rectangle,
                CornerRadius,
                CornerRadius);
            }
            else
            {
                drawingContext.DrawRectangle(
                    Fill,
                    Pen,
                    Rectangle);
            }

            drawingContext.Pop();
        }

        public override void Invalidate()
        {
            base.Invalidate();

            NotifyPropertyChanged("Width");
            NotifyPropertyChanged("Height");
            NotifyPropertyChanged("X");
            NotifyPropertyChanged("Y");
            NotifyPropertyChanged("CornerRadius");

            DrawingCanvas.DrawTrackers();
        }

        #region Static Helper Functions

        public static Rect GetNormalizedRectangle(double x1, double y1, double x2, double y2)
        {
            if (x2 < x1)
            {
                int tmp = (int)x2;
                x2 = x1;
                x1 = tmp;
            }

            if (y2 < y1)
            {
                int tmp = (int)y2;
                y2 = y1;
                y1 = tmp;
            }

            return new Rect(x1, y1, x2 - x1, y2 - y1);
        }

        public static Rect GetNormalizedRectangle(Point p1, Point p2)
        {
            return GetNormalizedRectangle(p1.X, p1.Y, p2.X, p2.Y);
        }

        public static Rect GetNormalizedRectangle(Rect r)
        {
            return GetNormalizedRectangle(r.X, r.Y, r.X + r.Width, r.Y + r.Height);
        }

        #endregion

        #region IHistoryable Members

        public ShapeMemento CreateMementoState()
        {
            var memento = new RectangleMemento();
            memento.SaveProperties(this);

            return memento;
        }

        public void ResetState(ShapeMemento memento)
        {
            memento.ResetProperties(this);
            this.Invalidate();
        }

        #endregion

        #region IPolygonShape Member

        public void AddShapeToPoligon(PolygonShape polygon)
        {
            polygon.AddLineSegment(new Point(Rectangle.X + Rectangle.Width, Rectangle.Y));
            polygon.AddLineSegment(new Point(Rectangle.X + Rectangle.Width, Rectangle.Y + Rectangle.Height));
            polygon.AddLineSegment(new Point(Rectangle.X, Rectangle.Y + Rectangle.Height));
            polygon.AddLineSegment(new Point(Rectangle.X, Rectangle.Y));
        }

        public Point StartPoint
        {
            get
            {
                return new Point(Rectangle.X, Rectangle.Y);
            }
        }

        public PolygonShape CreatePolygon()
        {
            var polygon = new PolygonShape(new Point(Rectangle.X, Rectangle.Y));

            polygon.AddLineSegment(new Point(Rectangle.X + Rectangle.Width, Rectangle.Y));
            polygon.AddLineSegment(new Point(Rectangle.X + Rectangle.Width, Rectangle.Y + Rectangle.Height));
            polygon.AddLineSegment(new Point(Rectangle.X, Rectangle.Y + Rectangle.Height));
			polygon.AddLineSegment(new Point(Rectangle.X, Rectangle.Y));

			polygon.JoinEndSegments = true;

            polygon.StrokeThickness = StrokeThickness;
            polygon.Stroke = Stroke;
            polygon.Fill = Fill;

            return polygon;
        }

        #endregion

        #region ICopyable Member

        public VectorShape Copy()
        {
            var shape = new RectangleShape(X, Y, Width, Height);
            shape.Fill = this.Fill;
            shape.Stroke = this.Stroke;
            shape.StrokeThickness = this.StrokeThickness;

            return shape;
        }

        #endregion

        
    }
}
